unit PanelWnd;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, uZeigerinstrument, uZeichenvorschrift, uPointFloat, ExtCtrls,
  StdCtrls, ComCtrls;

type
  TSimMetroPanel = class(TForm)
    Image1: TImage;
    Timer1: TTimer;
    paBremsmeldung: TPanel;
    Panel1: TPanel;
    tbFahrschalter: TTrackBar;
    tbVorwahl: TTrackBar;
    tbBremse: TTrackBar;
    cbTotmann: TCheckBox;
    LZB: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    cbTueren: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure tbFahrschalterChange(Sender: TObject);
    procedure tbVorwahlChange(Sender: TObject);
    procedure tbBremseChange(Sender: TObject);
    procedure cbTotmannClick(Sender: TObject);
    procedure LZBClick(Sender: TObject);
    procedure cbTuerenClick(Sender: TObject);
  private
    { Private declarations }
  public
    procedure WMCOPYDATA(var msg: TWMCopyData); message WM_COPYDATA;
    function SendIPCData(Data: String): Boolean;
    procedure Zeiger(VIst: Integer; LZB: Integer);
  end;

  TInputRecord = packed record
    Data: string[255];
  end;
  PInputRecord = ^TInputRecord;

  TOutputRecord = packed record
    Data: String[255];
  end;
  POutputRecord = ^TOutputRecord;

var
  SimMetroPanel: TSimMetroPanel;

  zi: TZeigerinstrument;
  zg: TZeigerinstrumentZeigerRund;
  zglzb: TZeigerinstrumentZeigerRund;

  WertVist: Integer = 0;
  WertLZB: Integer = 0;

implementation

{$R *.dfm}

function TSimMetroPanel.SendIPCData(Data: String): Boolean;
var
  MyRecord: POutputRecord;
  cds: TCopyDataStruct;
  hWnd: THandle;
begin
  GetMem(MyRecord, sizeof(TOutputRecord));
  try
    MyRecord.Data := Data;
    cds.dwData := 0;
    cds.cbData := sizeof(TOutputRecord);
    cds.lpData := MyRecord;
    hWnd := FindWindow('LS1', nil);
    Result := (hWnd = 0);
    SendMessage(hWnd, WM_COPYDATA, Handle, Integer(@cds));
  finally
    FreeMem(MyRecord, sizeof(TOutputRecord));
  end;
end;

procedure TSimMetroPanel.WMCOPYDATA(var msg: TWMCopyData);

  function HexToInt(HexNum: string): LongInt;
  begin
    Result:=StrToInt('$' + HexNum);
  end;

var
  Data: String[255];

begin
  Data := PInputRecord(msg.CopyDataStruct.lpData)^.Data;

  If Copy(Data, 1, 4) = 'XV01' then WertVist := HexToInt(Copy(Data, 7, 2));
  If Copy(Data, 1, 4) = 'XV00' then WertLZB  := HexToInt(Copy(Data, 7, 2));

  If Data = 'XU020001V' then paBremsmeldung.Font.Color := $0080FFFF;
  If Data = 'XU020000V' then paBremsmeldung.Font.Color := clBlack;
end;

procedure TSimMetroPanel.Zeiger(VIst: Integer; LZB: Integer);
begin
  zi.DrawHintergrundTo(Image1.Canvas.Handle);

  zglzb.Draw(Round((LZB + 45) * 1.20));
  zglzb.DrawTo(Image1.Canvas.Handle);
  zg.Draw(Round((VIst + 45) * 1.20));
  zg.DrawTo(Image1.Canvas.Handle);

  zi.DrawVordergrundTo(Image1.Canvas.Handle);

  Image1.Refresh;
end;

procedure TSimMetroPanel.FormCreate(Sender: TObject);
var
  zzp: TZeichenvorschriftPolygon;
  zzc: TZeichenvorschriftCircular;
  zzt: TZeichenvorschriftText;

  Rand:         Integer;
  FarbeRand:    TColor;
  FarbeInnen:   TColor;
  FarbeSchrift: TColor;
begin
  Randomize;
  DoubleBuffered := True;

  // Instrument vorbereiten
  Rand         := 15;
  FarbeRand    := RGB(48, 48, 48);
  FarbeInnen   := RGB(16, 16, 16);
  FarbeSchrift := RGB(240, 240, 240);

  zi := TZeigerinstrument.Create;

  zi.SetAbmessungen(Image1.Width, Image1.Height);
  zi.DrawVordergrund;
  zi.DrawHintergrund;

  // "Blech"
  Image1.Canvas.Brush.Color := clGreen;
  Image1.Canvas.FillRect(Rect(0, 0, Image1.Width, Image1.Height));

  // Rand
  zzc := TZeichenvorschriftCircular(zi.ZeichenvorschriftenVordergrund.GetZeichenvorschrift(zi.ZeichenvorschriftenVordergrund.AddZeichenvorschrift(zvCircular)));
  zzc.Color        := FarbeRand;
  zzc.Ursprung     := PointFloat(Image1.Width div 2, 200);
  zzc.RadiusAussen := Image1.Height div 2;
  zzc.RadiusInnen  := Image1.Width / 2 - Rand;


  // "Deuta-Bapperl"
  zzc := TZeichenvorschriftCircular(zi.ZeichenvorschriftenVordergrund.GetZeichenvorschrift(zi.ZeichenvorschriftenVordergrund.AddZeichenvorschrift(zvCircular)));
  zzc.Color        := RGB(160, 160, 160);
  zzc.Ursprung     := PointFloat(Image1.Width div 2, 200);
  zzc.RadiusAussen := 30;
  zzc.RadiusInnen  := 27;

  zzc := TZeichenvorschriftCircular(zi.ZeichenvorschriftenVordergrund.GetZeichenvorschrift(zi.ZeichenvorschriftenVordergrund.AddZeichenvorschrift(zvCircular)));
  zzc.Color        := FarbeRand;
  zzc.Ursprung     := PointFloat(Image1.Width div 2, 200);
  zzc.RadiusAussen := 27;


  // Hintergrund
  zzc := TZeichenvorschriftCircular(zi.ZeichenvorschriftenHintergrund.GetZeichenvorschrift(zi.ZeichenvorschriftenHintergrund.AddZeichenvorschrift(zvCircular)));
  zzc.Color        := FarbeInnen;
  zzc.Ursprung     := PointFloat(Image1.Width div 2, 200);
  zzc.RadiusAussen := Image1.Height div 2;
{
  zzt := TZeichenvorschriftText(zi.ZeichenvorschriftenVordergrund.GetZeichenvorschrift(zi.ZeichenvorschriftenVordergrund.AddZeichenvorschrift(zvText)));
  zzt.Color        := FarbeSchrift;
  zzt.Ursprung     := PointFloat(200, 200);
  zzt.Schriftart   := 'Terminal';
  zzt.Groesse      := 15;
  zzt.Text         := 'blah';
}
  zi.DrawVordergrund;
  zi.DrawHintergrund;

  // Tacho-Zeiger
  zg := TZeigerinstrumentZeigerRund.Create;
  zg.SetAbmessungen(Image1.Width, Image1.Height);
  zg.Ursprung := PointFloat(200, 200);

  zzp := TZeichenvorschriftPolygon(zg.Zeichenvorschriften.GetZeichenvorschrift(zg.Zeichenvorschriften.AddZeichenvorschrift(zvPolygon)));
  zzp.Color        := RGB(240, 190, 50);
  zzp.AddPunkt(PointFloat(193, 200));
  zzp.AddPunkt(PointFloat(193, 320));
  zzp.AddPunkt(PointFloat(200, 340));
  zzp.AddPunkt(PointFloat(207, 320));
  zzp.AddPunkt(PointFloat(207, 200));

  zzp := TZeichenvorschriftPolygon(zg.Zeichenvorschriften.GetZeichenvorschrift(zg.Zeichenvorschriften.AddZeichenvorschrift(zvPolygon)));
  zzp.Color        := RGB(120, 95, 25);
  zzp.AddPunkt(PointFloat(199, 200));
  zzp.AddPunkt(PointFloat(199, 310));
  zzp.AddPunkt(PointFloat(200, 330));
  zzp.AddPunkt(PointFloat(201, 310));
  zzp.AddPunkt(PointFloat(201, 200));

  // LZB-Zeiger

  zglzb := TZeigerinstrumentZeigerRund.Create;
  zglzb.SetAbmessungen(Image1.Width, Image1.Height);
  zglzb.Ursprung := PointFloat(200, 200);

  zzp := TZeichenvorschriftPolygon(zglzb.Zeichenvorschriften.GetZeichenvorschrift(zglzb.Zeichenvorschriften.AddZeichenvorschrift(zvPolygon)));
  zzp.Color        := RGB(240, 0, 0);
  zzp.AddPunkt(PointFloat(193, 398));
  zzp.AddPunkt(PointFloat(193, 380));
  zzp.AddPunkt(PointFloat(200, 360));
  zzp.AddPunkt(PointFloat(207, 380));
  zzp.AddPunkt(PointFloat(207, 398));

  zzp := TZeichenvorschriftPolygon(zglzb.Zeichenvorschriften.GetZeichenvorschrift(zglzb.Zeichenvorschriften.AddZeichenvorschrift(zvPolygon)));
  zzp.Color        := RGB(120, 0, 0);
  zzp.AddPunkt(PointFloat(199, 398));
  zzp.AddPunkt(PointFloat(199, 380));
  zzp.AddPunkt(PointFloat(200, 360));
  zzp.AddPunkt(PointFloat(201, 380));
  zzp.AddPunkt(PointFloat(201, 398));
end;

procedure TSimMetroPanel.FormDestroy(Sender: TObject);
begin
  zi.Free;
  zg.Free;
  zglzb.Free;
end;

procedure TSimMetroPanel.Timer1Timer(Sender: TObject);
begin
  Zeiger(WertVist, WertLZB);
end;

procedure TSimMetroPanel.tbFahrschalterChange(Sender: TObject);
begin
  If tbFahrschalter.Position = 0
    then SendIPCData('XU010000Y')
      else SendIPCData('XU010001Y');
end;

procedure TSimMetroPanel.tbVorwahlChange(Sender: TObject);
begin
  SendIPCData(Format('XV01000%dY', [7 - tbVorwahl.Position]));
end;

procedure TSimMetroPanel.tbBremseChange(Sender: TObject);
begin
  SendIPCData(Format('XV0000%.2xY', [$D1 - (tbBremse.Position * 2)]));
end;

procedure TSimMetroPanel.cbTotmannClick(Sender: TObject);
begin
  If not cbTotmann.Checked
    then SendIPCData('XU000001Y')
      else SendIPCData('XU000000Y');
end;

procedure TSimMetroPanel.LZBClick(Sender: TObject);
begin
  SendIPCData('XU150000Y');
end;

procedure TSimMetroPanel.cbTuerenClick(Sender: TObject);
begin
  If not cbTueren.Checked
    then SendIPCData('XU200001Y')
      else SendIPCData('XU200000Y');

end;

end.
